﻿package game.network.api.fb.net {

	import game.encrypt.PNGEncoder;
	import game.network.api.fb.utils.PostRequest;

	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.events.SecurityErrorEvent;
	import flash.net.FileReference;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.net.URLVariables;
	import flash.utils.ByteArray;

	public class AbstractFacebookRequest {

		protected var urlLoader:URLLoader;
		protected var urlRequest:URLRequest;
		protected var _rawResult:String;
		protected var _data:Object;
		protected var _success:Boolean;
		protected var _url:String;
		protected var _requestMethod:String;
		protected var _callback:Function;

		public function AbstractFacebookRequest ():void {

		}

		public function get rawResult ():String {
			return _rawResult;
		}

		public function get success ():Boolean {
			return _success;
		}

		public function get data ():Object {
			return _data;
		}

		public function callURL (callback:Function, url:String = "", locale:String = null):void {
			_callback = callback;
			urlRequest = new URLRequest(url.length ? url:_url);

			if (locale) {
				var data:URLVariables = new URLVariables();
				data.locale = locale;
				urlRequest.data = data;
			}
			loadURLLoader ();
		}

		public function set successCallback (value:Function):void {
			_callback = value;
		}

		protected function isValueFile (value:Object):Boolean {
			return (value is FileReference || value is Bitmap || value is BitmapData || value is ByteArray);
		}

		protected function objectToURLVariables (values:Object):URLVariables {
			var urlVars:URLVariables = new URLVariables();
			if (values == null) {
				return urlVars;
			}

			for (var n:String in values) {
				urlVars[n] = values[n];
			}

			return urlVars;
		}

		public function close ():void {
			if (urlLoader != null) {
				urlLoader.removeEventListener ( Event.COMPLETE,						handleURLLoaderComplete );
				urlLoader.removeEventListener ( IOErrorEvent.IO_ERROR,				handleURLLoaderIOError );
				urlLoader.removeEventListener ( SecurityErrorEvent.SECURITY_ERROR,	handleURLLoaderSecurityError );

				try {
					urlLoader.close ();
				} catch (e:Error ) {
					
				}

				urlLoader = null;
			}
		}

		protected function loadURLLoader ():void {
			urlLoader = new URLLoader();
			urlLoader.addEventListener ( Event.COMPLETE,					handleURLLoaderComplete, false, 0, false );
			urlLoader.addEventListener ( IOErrorEvent.IO_ERROR,				handleURLLoaderIOError, false, 0, true );
			urlLoader.addEventListener ( SecurityErrorEvent.SECURITY_ERROR,	handleURLLoaderSecurityError, false, 0, true );

			urlLoader.load (urlRequest);
		}

		protected function handleURLLoaderComplete (event:Event):void {
			handleDataLoad (urlLoader.data);
		}

		protected function handleDataLoad (result:Object, dispatchCompleteEvent:Boolean = true):void {

			_rawResult = result as String;
			_success = true;

			try {
				_data = JSON.parse(_rawResult);
			} catch (e: * ) {
				_data = _rawResult;
				_success = false;
			}

			handleDataReady ();

			if (dispatchCompleteEvent) {
				dispatchComplete ();
			}
		}

		protected function handleDataReady ():void {

		}

		protected function dispatchComplete ():void {
			if (_callback != null) {
				_callback (this);
			}
			close ();
		}

		protected function handleURLLoaderIOError (event:IOErrorEvent):void {
			_success = false;
			_rawResult = (event.target as URLLoader).data;

			if (_rawResult != '') {
				try {
					_data = JSON.parse(_rawResult);
				} catch (e: * ) {
					_data = {type:'Exception',message:_rawResult};
				}
			} else {
				_data = event;
			}

			dispatchComplete ();
		}

		protected function handleURLLoaderSecurityError (event:SecurityErrorEvent):void {
			_success = false;
			_rawResult = (event.target as URLLoader).data;

			try {
				_data = JSON.parse((event.target as URLLoader).data);
			} catch (e: * ) {
				_data = event;
			}

			dispatchComplete ();
		}

		protected function extractFileData (values:Object):Object {
			if (values == null) {
				return null;
			}

			var fileData:Object;
			if (isValueFile(values)) {
				fileData = values;
			} else if (values != null) {
				for (var n:String in values) {
					if (isValueFile(values[n])) {
						fileData = values[n];
						delete values[n];
						break;
					}
				}
			}

			return fileData;
		}

		protected function createUploadFileRequest (fileData:Object, values:Object = null):PostRequest {
			var post:PostRequest = new PostRequest();

			if (values) {
				for (var n:String in values) {
					post.writePostData (n, values[n]);
				}
			}

			if (fileData is Bitmap) {
				fileData = (fileData as Bitmap).bitmapData;
			}

			if (fileData is ByteArray) {
				post.writeFileData (values.fileName, fileData as ByteArray, values.contentType);

			} else if (fileData is BitmapData) {
				var ba:ByteArray = PNGEncoder.encode(fileData as BitmapData);
				post.writeFileData (values.fileName, ba, 'image/png');
			}

			post.close ();
			urlRequest.contentType = 'multipart/form-data; boundary=' + post.boundary;

			return post;
		}

		public function toString ():String {
			return urlRequest.url + (urlRequest.data == null ? '' : '?' + unescape(urlRequest.data.toString()));
		}
	}
}